Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Rework advanced filters screen reader text generation #1099

Merged
merged 8 commits into from
Jan 8, 2019

Conversation

jeffstieler
Copy link
Contributor

@jeffstieler jeffstieler commented Dec 15, 2018

Based on conversation here: #1089 (comment)

This PR seeks to:

  • Only describe full filter if all values are set
  • Describe each input more precisely

Notes:

There is an opportunity to DRY up the markup in the render of NumberFilter, SearchFilter, and SelectFilter, but I've left that undone as it might be a premature optimization. I can certainly turn that into another component if we decide that's cleanup worth doing.

Also, this PR adds a utility method called textContent(). It's essentially react-addons-text-content - I made the decision to just copy pasta the code into our project since the dependency is rather small and hasn't been updated in 3 years.

To test:

  • Navigate to devdocs, filters component
  • Add a filter of each type (order status, products, item quantity)
  • Verify that the <legend> for each doesn't change when interacting the the component
  • Verify that a <div> with class screen-reader-text is rendered only when all of the filter inputs have values

@jeffstieler jeffstieler self-assigned this Dec 15, 2018
@probot-autolabeler probot-autolabeler bot added focus: components Issues for woocommerce components Packages labels Dec 15, 2018
@jeffstieler jeffstieler force-pushed the fix/advanced-filters-legend-text branch from 9fa1d5f to 579968b Compare December 18, 2018 18:07
@jeffstieler jeffstieler added [Status] Needs Review focus: accessibility The issue/PR is related to accessibility. and removed status: in progress labels Dec 18, 2018
@jeffstieler jeffstieler requested a review from a team December 18, 2018 18:08
Copy link
Collaborator

@psealock psealock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good @jeffstieler !

I noted a couple small things and a comment on unread screenReaderText.

import { textContent } from '../utils';

describe( 'textContent()', () => {
test( 'should be got text `Hello World`', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be got text => should get text

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 9ce4d9e.

onChange={ onChange }
/>
: <TextControlWithAffixes
prefix={ <span dangerouslySetInnerHTML={ { __html: currencySymbol } } /> }
className="woocommerce-filters-advanced__input"
type="number"
value={ value }
aria-label={ label }
onChange={ onChange }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you can add a prop min="0" to prevent negative numbers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's handle this in a separate PR - the NumberFilter component doesn't have any sort of input validation yet.

<span className="screen-reader-text">
{ screenReaderText }
</span>
) }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Chrome and VoiceOver, this screenReaderText never gets read. I see it appropriately added to the DOM when the sentence is complete, however.

Sorry if this has been previously discussed, but would it not make sense to add screenReaderText to the legend?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not read even when you move to it?

It's not meant to be automatically read, as that interrupts the content entry - having it in legend is too noisy, and why @jeffstieler is doing all this work 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't be tabbed to, but if you use the VO controls you'll navigate to it after the last filter input, before the remove button.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but if you use the VO controls you'll navigate to it after the last filter input

via tabbing? Or is there another method?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I figured out how to navigate to the text using VO controls. I'm not a VO power user (yet), so forgive my novice comment, but I'm not experiencing the input being too noisy on master -- the legend only gets read when the fieldset has focus.

I assumed VO users would tab their way through a form, instead of using the arrow controls to read text in a span, and by doing so skip right over the text being added in this PR. Is this assumption wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed VO users would tab their way through a form, instead of using the arrow controls to read text in a span, and by doing so skip right over the text being added in this PR. Is this assumption wrong?

I'm not knowledgeable enough to say - I'm new to a11y 🙂. I defer to @ryelle.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this assumption wrong?

It's over-simplifying, not exactly wrong – screen reader users will tab to move through interactive components (forms, buttons, etc), but they'll use the arrow nav to move through the page's full contents (otherwise they'd never read non-interactive page content). They might also use other navigation methods (skipping through headings, or a list of links, or a list of buttons, etc).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, I don't know what a real user would do in this scenario - but this approach is better than interrupting the user while they're typing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, thank you for the clarification.

Copy link
Member

@ryelle ryelle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with VoiceOver + Safari, and it's working as expected. I'm not exactly sure why we need textContent, though, can you explain that a little more?

@jeffstieler
Copy link
Contributor Author

I'm not exactly sure why we need textContent, though, can you explain that a little more?

I initially introduced that so we'd be passing a string to wp.a11y.speak(). Let me double check to see if that's still needed..

@jeffstieler
Copy link
Contributor Author

jeffstieler commented Dec 18, 2018

I'm not exactly sure why we need textContent, though, can you explain that a little more?

I initially introduced that so we'd be passing a string to wp.a11y.speak(). Let me double check to see if that's still needed..

In testing, removing textContent() results in the following markup:

<span class="screen-reader-text">Item Quantity is <span>Less Than</span> <span>1</span></span>

Which VoiceOver requires several interactions to completely read - 3 in total for this example. Using textContent() to extract only the text content results in VO reading the full sentence ("Item Quantity is Less Than 1") once the component is navigated to.

Edit: even using <Fragment /> instead of <span /> for the interpolated components results in the same behavior.

@jeffstieler jeffstieler force-pushed the fix/advanced-filters-legend-text branch from 9ce4d9e to 079ff48 Compare January 3, 2019 20:16
@jeffstieler
Copy link
Contributor Author

Bumping for a resolution to the textContent() question (#). cc: @ryelle

@ryelle
Copy link
Member

ryelle commented Jan 3, 2019

@jeffstieler That confused me a little because spans are not supposed to create breaks like that. This seems to be a Safari vs Chrome difference - Safari + VO doesn't break the nested spans apart, but Chrome + VO does. If you switch the wrapper (the element with screen-reader-text) to a div, it reads correctly in both cases.

<div class="screen-reader-text">Item Quantity is <span>Less Than</span> <span>1</span></div>

@jeffstieler
Copy link
Contributor Author

@ryelle it seems that VO (even in Safari) doesn't cope well with line breaks in the HTML. In my testing (on this PR) using an outer <div> with inner <span>s still takes multiple key presses to read the full phrase of "Item Quantity is Less Than 1".

Here's a screen capture: https://cloudup.com/c_Ne8_uyoj3 (you can see the selected VO element, the VO overlay screen, and the markup of the screen-reader-text div all in frame)

I'll look in/around the interpolateComponents() to see if there's a culprit for the line breaks.

@ryelle
Copy link
Member

ryelle commented Jan 4, 2019

Hm, even with linebreaks in a plain HTML page, VoiceOver reads it as one line for me

<div class="screen-reader-text">
	Item Quantity is 
	<span>Less Than</span> 
	<span>1</span>
</div>

can you push up your latest changes so I can test it out myself?

@jeffstieler
Copy link
Contributor Author

Perhaps then I'm not navigating correctly? I'm using Control + Option + Right arrow to move between readable elements.

Pushed up my changes - 2532539.

@ryelle
Copy link
Member

ryelle commented Jan 4, 2019

I figured it out – the wp core CSS for .screen-reader-text also puts styles on .screen-reader-text span, and that triggers VO to read the spans as individual items 🙃 In my testing, I was just creating plain HTML pages with no CSS, to test the markup… not thinking that the screen-reader-text class did that.

Edit: You should try out using the class ui-helper-hidden-accessible instead of screen-reader-text – it should work but I think something is still interacting with it, but I don't know if that's just a local bug. You might have to bring back textContent after all.

@jeffstieler
Copy link
Contributor Author

@ryelle (Following up on a Slack convo we had)

Changing to the ui-helper-hidden-accessible didn't solve the problem - apparently WP's line-height (#) is causing the problem.

Even while resetting the line-height to either initial or normal seems to fix the Safari VO issue, the text of the spans are all concatenated, ignoring padding whitespace. This results in the screen reader reading Item Quantity is Between$4.00and$6.00 which causes it to read "between dollar sign four point zero zero ..." instead of "between four dollars and zero zero cents ...".

I don't believe any of these issues were present with the textContent() utility function I introduced. I'm going to go back to that logic and test these scenarios. If they are no longer problems, I think we should move forward with that solution.

@jeffstieler jeffstieler force-pushed the fix/advanced-filters-legend-text branch from 2532539 to 079ff48 Compare January 4, 2019 20:27
@jeffstieler
Copy link
Contributor Author

Tested with the (formerly) previous commit - everything is fine there. I've deleted the commit that removed the usage of textContent().

Copy link
Member

@ryelle ryelle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is reading correctly now, no pauses/broken sentences. Thanks for all your work on this!

@jeffstieler jeffstieler merged commit eaffb0d into master Jan 8, 2019
@jeffstieler jeffstieler deleted the fix/advanced-filters-legend-text branch January 8, 2019 15:45
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
focus: accessibility The issue/PR is related to accessibility. focus: components Issues for woocommerce components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants